package com.mind.customer.handler.tongwei;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mind.api.WebServiceClient;
import com.mind.common.utils.StringUtils;
import com.mind.customer.domain.vo.*;
import com.mind.customer.mapper.AjCheckResultMapper;
import com.mind.customer.mapper.AjReportResultMapper;
import com.mind.customer.mapper.AjRuleMapper;
import com.mind.customer.mapper.AjTicketTaskMapper;
import com.mind.customer.template.TemplateEngine;
import com.mind.customer.utils.CateUtils;
import com.mind.customer.utils.EnvUtils;
import com.mind.system.domain.*;
import com.mind.system.domain.vo.CateResult;
import com.mind.system.mapper.SysConfigMapper;
import jakarta.annotation.Resource;
import lombok.extern.log4j.Log4j2;
import okhttp3.*;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.xml.bind.JAXBException;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;

import static com.mind.customer.domain.mapping.ConditionRuleMapping.getCallbackResult;

@Component
@Log4j2
public class CheckHandler {
    @Resource
    private AjReportResultMapper reportResultMapper;
    @Resource
    private AjCheckResultMapper checkResultMapper;
    @Resource
    private AjRuleMapper ruleMapper;

    @Resource
    private WebServiceClient webServiceClient;

    @Resource
    private AjTicketTaskMapper ticketTaskMapper;

    @Resource
    private CateUtils cateUtils;

    @Resource
    private EnvUtils envUtils;

    @Resource
    private CallbackHandler callbackHandler;

    @Resource
    private SysConfigMapper sysConfigMapper;
    private String rule_analysis_url;

    public TaskResult handle(AjTicketTask task) throws JAXBException {
        List<AjCheckResult> checkResults = checkResultMapper.selectByLastVersion(task.getTicketId(), task.getVersion());
        if (!CollectionUtils.isEmpty(checkResults)) {
            log.error("该单据：{} 版本：{}已经生成", task.getTicketId(), task.getVersion());
            return null;
        }
        TaskResult taskResult = new TaskResult();

        CateResult offsetCateResult = cateUtils.existsCate("未上线", task.getBusinessCate(), task.getTicketType());
        CateResult specialResult = cateUtils.existsCate("混报业务", task.getBusinessCate(), task.getTicketType());
        List<AjRule> rules;
        // 存在未上线小类
        if (offsetCateResult.getExists()) {
            rules = offsetCateResult.getRules();
        }
        //存在特殊小类
        else if (specialResult.getExists()) {
            rules = specialResult.getRules();
        } else {

            List<String> businessCateList = new ArrayList<>();
            if (StringUtils.isNotEmpty(task.getBusinessCate())) {
                businessCateList = Arrays.asList(task.getBusinessCate().split(","));
            }
            rules = ruleMapper.selectByParams(task.getTicketType(), businessCateList, null);

        }
        SmartCheckResult checkResult = smartCheck(task, rules);
        // 回写查验状态
        ticketTaskMapper.updateTicketTask(new AjTicketTask() {{
            setId(task.getId());
            setPassCount(checkResult.getPassList().stream().filter(r -> r).count());
            setTotalCount((long) checkResult.getPassList().size());
            setCheckResult(checkResult.getIsPass() ? 1 : 2);
        }});
        //上一版本的处理结果是待处理或者是首次推送触发回调
        AjTicketTask ticketTask = ticketTaskMapper.selectByVersion(task.getTicketId(), task.getVersion() - 1);
        if (ticketTask != null && ticketTask.getHandleResult() == 1) {
            ticketTaskMapper.updateTicketTask(new AjTicketTask() {{
                setId(ticketTask.getId());
                setHandleNickname("系统");
                setHandleResult(4);
            }});
        }
        // 待处理 1， 退影像 5 不回调
        if (envUtils.getPlatform().equals("tongwei") && (task.getVersion() == 1 || (ticketTask != null && !CollectionUtils.contains(Arrays.asList(1, 5).listIterator(), ticketTask.getHandleResult())))) {
            callbackHandler.handle(checkResult.getCallbackResult(), task, checkResult.getIsPass() ? "1" : "2", checkResult.getRulePassMapping());
        }


        return taskResult;
    }

    private void autoSelectCallbackResult(Set<String> callbackResult, boolean isSinglePass, String[] ruleSuccessSystemCall, String[] ruleFailSystemCall) {
        if (isSinglePass && ruleSuccessSystemCall != null && ruleSuccessSystemCall.length > 0) {
            callbackResult.add(getCallbackResult(ruleSuccessSystemCall[0]));
        } else if (!isSinglePass && ruleFailSystemCall != null && ruleFailSystemCall.length > 0) {
            callbackResult.add(getCallbackResult(ruleFailSystemCall[0]));
        }
    }

    @Resource
    TemplateEngine templateEngine;

    public SmartCheckResult smartCheck(AjTicketTask task, List<AjRule> rules) {
        AjReportResult reportResult = reportResultMapper.selectReportResultByTicketId(task.getTicketId(), task.getVersion());
        String reportResultResult = reportResult.getResult();
        ObjectMapper objectMapper = new ObjectMapper();


        // rule_url
        if (rule_analysis_url == null || rule_analysis_url.length() == 0) {
            SysConfig ruleUrlConfig = sysConfigMapper.checkConfigKeyUnique("RULE_ANALYSIS_URL");
            if (ruleUrlConfig != null && StringUtils.isNotEmpty(ruleUrlConfig.getConfigValue())) {
                rule_analysis_url = ruleUrlConfig.getConfigValue();
            } else {
                rule_analysis_url = "http://127.0.0.1:9001/jsonrpc";
            }
        }

        log.info("规则明细条数：{}, 业务小类：{}", rules.size(), task.getBusinessCate());
        List<AjCheckResult> checkResultList = new ArrayList<>();
        boolean isPass = false;
        List<Boolean> isPassList = new ArrayList<>();
        Map<Long, String> rulePassMapping = new HashMap<>();
        Set<String> callbackResult = new HashSet<>();
        for (AjRule rule : rules) {
            RuleDetailEditor ruleDetailEditor = JSONObject.parseObject(rule.getRuleDetail().getEditor(), RuleDetailEditor.class);
            log.info("规则名称： {}", rule.getRuleDetail().getName());
            boolean isSinglePass = false;
            boolean conditionIsError = false;
            String relatedData = "{}";
            // 如果解析器报错，则直接返回
            boolean conditionIsPass = false;
            String verificationInfo = "{}";
            switch (rule.getRuleDetail().getEditMode()) {
                case SysFunc:
                    switch (ruleDetailEditor.getFuncName()) {
                        default:
                        case "AI":
                            try {
                                String template = ruleDetailEditor.getRule().toString();
                                JsonNode data = objectMapper.readTree(reportResultResult);
                                List<String> renders = templateEngine.render(template, data);
                                List<Object> result = new ArrayList<>();
                                int passCount = 0;
                                for (String render : renders) {
                                    Request ruleAiReq = getRuleAiReq(render);
                                    OkHttpClient client = new OkHttpClient.Builder()
                                            .connectTimeout(30, TimeUnit.SECONDS) // 连接超时时间为无限
                                            .readTimeout(30, TimeUnit.SECONDS)    // 读取超时时间为无限
                                            .writeTimeout(30, TimeUnit.SECONDS)   // 写入超时时间为无限
                                            .build();
                                    Response response = client.newCall(ruleAiReq).execute();
                                    // 检查响应码
                                    if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
                                    // 打印响应体
                                    String bodyStr = response.body().string();
                                    AIRuleRep aiRuleRep = JSON.parseObject(bodyStr, AIRuleRep.class);
                                    AIRuleRep.JsonData resultData = aiRuleRep.getData().getJsonData();
                                    HashMap<String, Object> objectObjectHashMap = new HashMap<>();
                                    objectObjectHashMap.put("analysisProcess", resultData.getAnalysisProcess());
                                    objectObjectHashMap.put("passed", resultData.isPassed());
                                    objectObjectHashMap.put("reason", resultData.getReason());
                                    objectObjectHashMap.put("template", template);
                                    objectObjectHashMap.put("render", render);
                                    result.add(objectObjectHashMap);
                                    if (resultData.isPassed()) {
                                        passCount++;
                                    }
                                }
                                isSinglePass = passCount == renders.size();
                                relatedData = JSONObject.toJSONString(result);
                                conditionIsError = true;
                            } catch (Exception e) {
                                e.printStackTrace();
                                throw new RuntimeException(e);
                            }
                            break;
                    }
                    break;
                case Order:
                case Scale:
                default:
                    String body = webServiceClient.call(rule_analysis_url, JSONObject.toJSONString(new HashMap<String, Object>() {{
                        put("method", "/intelligentVerification");
                        put("params", new HashMap<String, Object>() {{
                            put("rule_detail_string", rule.getRuleDetail().getEditor());
                            put("data_string", reportResultResult);
                        }});

                    }}), null);
                    JsonrpcResult jsonrpcResult = JSONObject.parseObject(body, JsonrpcResult.class);
                    if (jsonrpcResult == null || jsonrpcResult.getError() == null || jsonrpcResult.getError().getCode() != 200) {
                        log.error("解析器报错:{},规则名称:{}", jsonrpcResult, rule.getRuleDetail().getName());
                        if (jsonrpcResult != null && jsonrpcResult.getError() != null) {
                            verificationInfo = new JSONObject() {{
                                put("errors", Collections.singletonList(jsonrpcResult.getError().getMessage()));
                            }}.toString();
                        }
                        conditionIsPass = true;
                    } else {
                        RuleResult ruleResult = jsonrpcResult.getResult();
                        conditionIsPass = ruleResult.getConditionIsPass();
                        conditionIsError = ruleResult.getConditionIsError();
                        relatedData = JSONObject.toJSONString(ruleResult);
                        isSinglePass = ruleResult.getIsPass();
//                verificationInfo = JSONObject.toJSONString(ruleResult.getVerificationInfo());
                    }
                    break;
            }

            rulePassMapping.put(rule.getRuleDetailId(), isSinglePass ? "1" : "2");

            // 如果单条规则不通过，则直接返回
            boolean finalIsSinglePass = isSinglePass;
            String finalRelatedData = relatedData;

            String finalVerificationInfo = verificationInfo;
            boolean finalConditionIsPass = conditionIsPass;
            boolean finalConditionIsError = conditionIsError;
            if (!(!finalConditionIsError && !finalConditionIsPass)) {
                isPassList.add(isSinglePass);
            }

            checkResultList.add(new AjCheckResult() {{
                setTicketId(task.getTicketId());
                setTicketType(task.getTicketType());
                setRuleId(rule.getId());
                setRuleDetailId(rule.getRuleDetailId());
                setRuleDesc(rule.getRuleDetail().getDesc());
                setAlert(rule.getRuleDetail().getAlert());
                setRuleName(rule.getRuleDetail().getName());
                setVersion(task.getVersion());
                setBusinessCate(task.getBusinessCate());
                setVerificationInfo(finalVerificationInfo);
                setRelatedData(finalRelatedData);
                setStatus((!finalConditionIsError && !finalConditionIsPass) ? 4 : finalIsSinglePass ? 1 : 2);
                setViewGroup(rule.getViewGroup());
                setRiskLevel(rule.getRiskLevel());
            }});
            // 没有配置规则编辑器
            if (ruleDetailEditor != null) {
                autoSelectCallbackResult(callbackResult, conditionIsPass, ruleDetailEditor.getConditionSuccessSystemCall(), ruleDetailEditor.getConditionFailSystemCall());
                autoSelectCallbackResult(callbackResult, isSinglePass, ruleDetailEditor.getRuleSuccessSystemCall(), ruleDetailEditor.getRuleFailSystemCall());
            }
        }
        // 保底规则
        if (checkResultList.stream().noneMatch(e -> e.getStatus() != 4)) {
            rules = ruleMapper.selectByParams(null, null, 1);
            try {
                insertCheckResult(task, rules.get(0));

            } catch (IndexOutOfBoundsException e) {
                e.printStackTrace();
                throw new RuntimeException("保底规则为空");
            }
        }
//        checkResultMapper.deleteCheckResultByTicketId(task.getTicketId());
//        checkLastVersionResultAndUpdate(task);
        if (checkResultList.size() > 0) {
            checkResultMapper.insertCheckResultBatch(checkResultList);
        }
        log.info("检查结果:{}", isPassList);
        if (!CollectionUtils.isEmpty(isPassList)) {
            isPass = isPassList.stream().allMatch((e) -> e);
        }
        boolean finalIsPass = isPass;
        return new SmartCheckResult() {{
            setCallbackResult(callbackResult);
            setIsPass(finalIsPass);
            setPassList(isPassList);
            setRulePassMapping(rulePassMapping);
        }};
    }

    private Request getRuleAiReq(String content) {
        String ndUrl = "http://nd.fanhaninfo.test";
        SysConfig ndAiUrlConfig = sysConfigMapper.checkConfigKeyUnique("NC_URL");
        if (ndAiUrlConfig != null && StringUtils.isNotEmpty(ndAiUrlConfig.getConfigValue())) {
            ndUrl = ndAiUrlConfig.getConfigValue();
        }
        String path = "/api/server/nd/service/RULE_LMM";
        SysConfig ndAiPathConfig = sysConfigMapper.checkConfigKeyUnique("ND_AI_PATH");
        if (ndAiPathConfig != null && StringUtils.isNotEmpty(ndAiPathConfig.getConfigValue())) {
            path = ndAiPathConfig.getConfigValue();
        }
        SysConfig ndAiToken = sysConfigMapper.checkConfigKeyUnique("NC_TOKEN");
        String secret = "";
        if (ndAiToken != null && StringUtils.isNotEmpty(ndAiToken.getConfigValue())) {
            secret = ndAiToken.getConfigValue();
        }
        AIRuleReq aiRuleReq = new AIRuleReq();
        AIRuleReq.Asset asset = new AIRuleReq.Asset();
        asset.setType("json");
        asset.setJsonData(new HashMap<String, String>() {{
            put("content", content);
        }});
        aiRuleReq.setAsset(asset);
        RequestBody requestBody = RequestBody.create(
                MediaType.parse("application/json; charset=utf-8"),
                JSON.toJSONString(aiRuleReq)
        );
        Request request = new Request.Builder()
                .url(ndUrl + path)
                .post(requestBody).header("secret", secret)
                .build();

        return request;
    }

    private SmartCheckResult insertCheckResult(AjTicketTask task, AjRule rule) {
        checkResultMapper.insertCheckResult(new AjCheckResult() {{
            setTicketId(task.getTicketId());
            setTicketType(task.getTicketType());
            setRuleId(rule.getId());
            setRuleDetailId(rule.getRuleDetailId());
            setRuleDesc(rule.getRuleDetail().getDesc());
            setAlert(rule.getRuleDetail().getAlert());
            setRuleName(rule.getRuleDetail().getName());
            setVersion(task.getVersion());
            setBusinessCate(task.getBusinessCate());
            setViewGroup(rule.getViewGroup());
            setRelatedData("{}");
            setStatus(2);
            setRiskLevel(rule.getRiskLevel());
        }});
        return new SmartCheckResult() {{
            setIsPass(false);
            setRulePassMapping(new HashMap<>(0));
            setCallbackResult(new HashSet<>());
        }};
    }

    /**
     * 检查上一个版本审核结果
     *
     * @param task
     */
    private void checkLastVersionResultAndUpdate(AjTicketTask task) {
        List<AjCheckResult> checkResultList = checkResultMapper.selectByLastVersion(task.getTicketId(), task.getVersion() - 1);
        for (AjCheckResult checkResult : checkResultList) {

            // 如果是人工处理
            if (checkResult.getStatus() == 2) {
                // 状态改成系统自动更新
                checkResultMapper.updateCheckResult(new AjCheckResult() {{
                    setId(checkResult.getId());
                    setStatus(3);
                }});

            }
        }
    }
}
